package com.sloth.bear.handler;

import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;

public class ScriptExecutionHandler extends TextWebSocketHandler {

    // 存储每个会话的正在执行的进程
    private final Map<String, Process> activeProcesses = new ConcurrentHashMap<>();
    // 存储每个会话的执行任务
    private final Map<String, CompletableFuture<Void>> activeTasks = new ConcurrentHashMap<>();

    @Override
    public void afterConnectionEstablished(WebSocketSession session) {
        System.out.println("WebSocket 连接已建立: " + session.getId());
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String command = message.getPayload();
        String sessionId = session.getId();
        
        // 检查是否是停止命令
        if ("STOP_DEPLOYMENT".equals(command)) {
            stopDeployment(session);
            return;
        }
        
        // 检查是否已有正在执行的部署
        if (activeProcesses.containsKey(sessionId)) {
            sendMessage(session, "已有部署正在执行中，请先停止当前部署或等待完成");
            return;
        }
        
        // 解析参数，支持新的4参数格式：env type app [module]
        String[] params = command.split(" ");
        if (params.length >= 3) {
            // 新格式：env type app [module]
            String env = params[0];
            String type = params[1]; 
            String app = params[2];
            String module = params.length >= 4 ? params[3] : "";
            CompletableFuture<Void> task = CompletableFuture.runAsync(() -> executeScript(session, env, type, app, module));
            activeTasks.put(sessionId, task);
        } else if (params.length >= 2) {
            // 兼容旧格式：env service [environment]
            String env = params[0];
            String service = params[1];
            String environment = params.length >= 3 ? params[2] : "";
            CompletableFuture<Void> task = CompletableFuture.runAsync(() -> executeScriptOld(session, env, service, environment));
            activeTasks.put(sessionId, task);
        } else {
            // 兼容旧的 "execute" 命令
            CompletableFuture<Void> task = CompletableFuture.runAsync(() -> executeScriptOld(session, "0", "0", ""));
            activeTasks.put(sessionId, task);
        }
    }

    private void executeScript(WebSocketSession session, String env, String type, String app, String module) {
        String sessionId = session.getId();
        Process process = null;
        
        try {
            // 构建部署类型描述
            String envText = "test".equals(env) ? "测试环境" : "生产环境";
            String typeText = "web".equals(type) ? "前端" : "server".equals(type) ? "后端" : "前端+后端";
            String appText = "app".equals(app) ? "APP" : "管理后台";
            String moduleText = !module.isEmpty() ? "-" + module : "";
            String deployType = envText + appText + typeText + moduleText;
            
            sendMessage(session, "开始执行" + deployType + "部署...");
            
            // 执行部署脚本 - 脚本在根目录
            String scriptPath = System.getProperty("user.dir") + "/sloth-bear-shell/waveup-deploy/deploy.sh";
            sendMessage(session, "脚本路径: " + scriptPath);
            
            // 构建命令并输出调试信息
            String[] command;
            if (!module.isEmpty()) {
                command = new String[]{"sh", scriptPath, env, type, app, module};
            } else {
                command = new String[]{"sh", scriptPath, env, type, app};
            }
            String commandStr = String.join(" ", command);
            sendMessage(session, "执行命令: " + commandStr);
            System.out.println("=== 执行部署脚本 ===");
            System.out.println("命令: " + commandStr);
            System.out.println("参数: env=" + env + ", type=" + type + ", app=" + app + 
                             (!module.isEmpty() ? ", module=" + module : ""));
            System.out.println("部署类型: " + deployType);
            System.out.println("工作目录: " + System.getProperty("user.dir"));
            System.out.println("==================");
            
            ProcessBuilder pb = new ProcessBuilder(command);
            process = pb.start();
            
            // 保存进程引用以便后续中断
            activeProcesses.put(sessionId, process);

            // 读取输出
            BufferedReader reader = new BufferedReader(
                new InputStreamReader(process.getInputStream(), "UTF-8"));
            BufferedReader errorReader = new BufferedReader(
                new InputStreamReader(process.getErrorStream(), "UTF-8"));

            String line;
            while ((line = reader.readLine()) != null) {
                // 检查进程是否被中断
                if (!activeProcesses.containsKey(sessionId)) {
                    sendMessage(session, "部署已被用户中断");
                    return;
                }
                sendMessage(session, line);
                Thread.sleep(100); // 模拟实时输出
            }

            // 读取错误输出，过滤掉常见的警告信息
            while ((line = errorReader.readLine()) != null) {
                // 检查进程是否被中断
                if (!activeProcesses.containsKey(sessionId)) {
                    sendMessage(session, "部署已被用户中断");
                    return;
                }
                
                if (!line.trim().isEmpty() && 
                    !line.contains("There is no tracking information") &&
                    !line.contains("NODE_ENV=test is not supported") &&
                    !line.contains("didn't resolve at build time") &&
                    !line.contains("Container") &&
                    !line.contains("git pull") &&
                    !line.contains("git branch --set-upstream-to")) {
                    sendMessage(session, "WARN: " + line);
                }
            }

            int exitCode = process.waitFor();
            if (activeProcesses.containsKey(sessionId)) {
                sendMessage(session, "脚本执行完成，退出码: " + exitCode);
            }

        } catch (InterruptedException e) {
            sendMessage(session, "部署被中断");
        } catch (Exception e) {
            sendMessage(session, "执行出错: " + e.getMessage());
        } finally {
            // 清理资源
            activeProcesses.remove(sessionId);
            activeTasks.remove(sessionId);
            
            if (process != null && process.isAlive()) {
                process.destroyForcibly();
            }
        }
    }

    // 停止部署方法
    private void stopDeployment(WebSocketSession session) {
        String sessionId = session.getId();
        
        Process process = activeProcesses.get(sessionId);
        CompletableFuture<Void> task = activeTasks.get(sessionId);
        
        if (process != null) {
            sendMessage(session, "正在停止部署...");
            
            // 首先尝试优雅关闭
            process.destroy();
            
            // 等待一段时间后强制关闭
            try {
                Thread.sleep(3000);
                if (process.isAlive()) {
                    process.destroyForcibly();
                    sendMessage(session, "部署已强制停止");
                }
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            }
            
            // 清理资源
            activeProcesses.remove(sessionId);
            if (task != null) {
                task.cancel(true);
                activeTasks.remove(sessionId);
            }
            
            sendMessage(session, "部署已停止");
        } else {
            sendMessage(session, "当前没有正在执行的部署任务");
        }
    }

    private void executeScriptOld(WebSocketSession session, String env, String service, String environment) {
        try {
            String deployType;
            switch (service) {
                case "0": deployType = "h5前端"; break;
                case "1": deployType = "h5后端"; break;
                case "2": deployType = "h5前后端"; break;
                case "3": deployType = "管理后台前端"; break;
                case "4": deployType = "管理后台后端"; break;
                case "5": deployType = "管理后台前后端"; break;
                default: deployType = "h5前端";
            }
            sendMessage(session, "开始执行" + deployType + "部署...");
            
            // 执行部署脚本 - 脚本在根目录
            String scriptPath = System.getProperty("user.dir") + "/sloth-bear-shell/waveup-deploy/deploy.sh";
            sendMessage(session, "脚本路径: " + scriptPath);
            
            // 构建命令并输出调试信息
            String[] command;
            if (!environment.isEmpty()) {
                command = new String[]{"sh", scriptPath, env, service, environment};
            } else {
                command = new String[]{"sh", scriptPath, env, service};
            }
            String commandStr = String.join(" ", command);
            sendMessage(session, "执行命令: " + commandStr);
            System.out.println("=== 执行部署脚本 ===");
            System.out.println("命令: " + commandStr);
            System.out.println("参数: env=" + env + ", service=" + service + " (" + deployType + ")" + 
                             (!environment.isEmpty() ? ", environment=" + environment : ""));
            System.out.println("工作目录: " + System.getProperty("user.dir"));
            System.out.println("==================");
            
            ProcessBuilder pb = new ProcessBuilder(command);
            Process process = pb.start();

            // 读取输出
            BufferedReader reader = new BufferedReader(
                new InputStreamReader(process.getInputStream(), "UTF-8"));
            BufferedReader errorReader = new BufferedReader(
                new InputStreamReader(process.getErrorStream(), "UTF-8"));

            String line;
            while ((line = reader.readLine()) != null) {
                sendMessage(session, line);
                Thread.sleep(100); // 模拟实时输出
            }

            // 读取错误输出，过滤掉常见的警告信息
            while ((line = errorReader.readLine()) != null) {
                if (!line.trim().isEmpty() && 
                    !line.contains("There is no tracking information") &&
                    !line.contains("NODE_ENV=test is not supported") &&
                    !line.contains("didn't resolve at build time") &&
                    !line.contains("Container") &&
                    !line.contains("git pull") &&
                    !line.contains("git branch --set-upstream-to")) {
                    sendMessage(session, "WARN: " + line);
                }
            }

            int exitCode = process.waitFor();
            sendMessage(session, "脚本执行完成，退出码: " + exitCode);

        } catch (Exception e) {
            sendMessage(session, "执行出错: " + e.getMessage());
        }
    }

    private void sendMessage(WebSocketSession session, String message) {
        try {
            if (session.isOpen()) {
                session.sendMessage(new TextMessage(message));
            }
        } catch (Exception e) {
            System.err.println("发送消息失败: " + e.getMessage());
        }
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) {
        System.err.println("WebSocket 传输错误: " + exception.getMessage());
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus closeStatus) {
        String sessionId = session.getId();
        System.out.println("WebSocket 连接已关闭: " + sessionId);
        
        // 清理该会话的所有资源
        Process process = activeProcesses.remove(sessionId);
        CompletableFuture<Void> task = activeTasks.remove(sessionId);
        
        if (process != null && process.isAlive()) {
            System.out.println("强制终止会话 " + sessionId + " 的部署进程");
            process.destroyForcibly();
        }
        
        if (task != null) {
            task.cancel(true);
        }
    }
}